#include "Acceptor.hpp"

namespace xww
{
    Acceptor::Acceptor(unsigned short port,const string &ip)
    :_addr(port,ip)
    ,_listenSock()
    {
        
    }

    Acceptor::~Acceptor()
    {
        // 析构函数中不需要做任何操作，因为Socket和InetAddress的析构函数会自动释放资源
    }

    void Acceptor::ready()
    {
        setReuseAddr(true); // 设置地址重用选项
        setReusePort(true); // 设置端口重用选项
        bind(); // 绑定套接字到地址
        listen(); // 开始监听
    }

    void Acceptor::bind()
    {
        //bind函数的用法？
        //参数：
        // 1. _listenSock.getfd()：获取监听套接字的文件描述符
        // 2. _addr.getInetAddrPtr()：获取InetAddress对象
        //    中的sockaddr_in结构体指针，表示要绑定的地址和端口
        // 3. sizeof(struct sockaddr_in)：指定地址结构体的大小
        int ret = ::bind(_listenSock.getfd(), (const struct sockaddr*)_addr.getInetAddrPtr(), sizeof(struct sockaddr_in));
        if(ret < 0)
        {
            perror("bind error");
            // 这里可以抛出异常或者处理错误
            // throw std::runtime_error("bind error");
        }
    }

    void Acceptor::listen()
    {
        int ret = ::listen(_listenSock.getfd(), 128); // 128是监听队列的最大长度
        if(ret < 0)
        {
            perror("listen error");
            // 这里可以抛出异常或者处理错误
            // throw std::runtime_error("listen error");
        }
    }

    //这个函数的用法？
    int Acceptor::accept()
    {
        int netfd = ::accept(_listenSock.getfd(),nullptr, nullptr);
        if(netfd < 0)
        {       
            perror("accept error");
            // 这里可以抛出异常或者处理错误
            // throw std::runtime_error("accept error");
        }
        return netfd; // 返回新连接的文件描述符

    }

    int Acceptor::getListenFd() const
    {
        return _listenSock.getfd(); // 返回监听套接字的文件描述符
    }
    
    void Acceptor::setReuseAddr(bool on)
    {
        int value = on;
        int ret = setsockopt(_listenSock.getfd(), SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
        if(ret < 0)
        {
            perror("setsockopt SO_REUSEADDR error");
            // 这里可以抛出异常或者处理错误
            // throw std::runtime_error("setsockopt SO_REUSEADDR error");
        }
    }

    void Acceptor::setReusePort(bool on)
    {
        int value = on;
        //int value  = on ? 1 : 0;//三元运算符怎么用？
                                // 三元运算符的语法是：条件 ? 真值 : 假值
                                // 如果on为true，则value为1；否则为0
                                // 这行代码的作用是根据on的值设置value为1或0
                                // 以便在后续的setsockopt调用中设置SO_REUSEPORT选项
                                // 这样可以控制是否允许端口重用
                                // 端口重用允许多个套接字绑定到同一个端口，
                                // 这在某些情况下可以提高资源利用率和性能
        int ret = setsockopt(_listenSock.getfd(), SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value));
        if(ret < 0)
        {
            perror("setsockopt SO_REUSEPORT error");
            // 这里可以抛出异常或者处理错误
            // throw std::runtime_error("setsockopt SO_REUSEPORT error");
        }
    }

} // end of namespace xww
